package org.example.repository.dialect.memory;

import org.example.repository.*;

import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Stream;

public class InMemoryRepository<T extends Entity<?>> implements Repository<T> {

    private final SortedMap<Object, T> data = new TreeMap<>();
    private final Schema schema;

    public InMemoryRepository(Schema schema) {
        this.schema = schema;
    }

    @Override
    public List<T> find(Query query) {
        Stream<T> stream = filterData(query);
        return stream.toList();
    }

    @Override
    public long count(Query query) {
        Stream<T> stream = filterData(query);
        return stream.count();
    }

    @Override
    public T findById(Object id) {
        Query _query = new Query().where(Condition.equals("id", id)).limit(1);
        Stream<T> stream = filterData(_query);
        return stream.findFirst().orElse(null);
    }

    @Override
    public T findFirst(Query query) {
        Query _query = new Query(query).limit(1);
        Stream<T> stream = filterData(_query);
        return stream.findFirst().orElse(null);
    }

    @Override
    public int add(T entity) {
        data.put(entity.getId(), entity);
        return 1;
    }

    @Override
    public int update(T entity, Condition where) {
        data.put(entity.getId(), entity);
        return 1;
    }

    @Override
    public void clear() {
        data.clear();
    }

    private Stream<T> filterData(Query query) {
        Stream<T> stream = data.values().stream();
        if (query != null) {
            QueryFilter<T> queryFilter = new QueryFilter<>(schema, query);
            stream = stream.filter(queryFilter);
            if (query.offset() != null) {
                stream = stream.skip(query.offset());
            }
            if (query.limit() != null) {
                stream = stream.limit(query.limit());
            }
        }
        return stream;
    }
}
